package org.pi.common.scripting

import javax.swing._;
import javax.swing.event._;
import jsyntaxpane.DefaultSyntaxKit;

class PragmaticSipRunner extends javax.swing.JPanel(new java.awt.BorderLayout()) {
	setMinimumSize(new java.awt.Dimension(320,200))
	private val self = this
	private var filename: String = null

	// http://code.google.com/p/jsyntaxpane/
    DefaultSyntaxKit.initKit();
	private val editor = new JEditorPane();	
    private val scrollPaneWithEditor = new JScrollPane(editor);
	private val output = new JEditorPane();	
    private val scrollPaneWithOutput = new JScrollPane(output);
    private val splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT) 
    
    editor.setContentType("text/scala");
    editor.setText("println(\"Hello World\")\n// insert code here and press 'run'.\n");
    scrollPaneWithEditor.setBorder(new javax.swing.border.TitledBorder("source code"))
    output.setEditable(false);
    scrollPaneWithOutput.setBorder(new javax.swing.border.TitledBorder("output"))
	// alternative "editor":
	// private val editor = new javax.swing.JTextArea("println(\"Hello World\")");

	private val runAction = new AbstractAction() { 
		putValue( Action.NAME, "run script" ); 
		//putValue( Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_R, java.awt.event.InputEvent.CTRL_MASK) )
		putValue( Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_F5, java.awt.event.InputEvent.CTRL_MASK) )
		putValue( Action.DISPLAYED_MNEMONIC_INDEX_KEY, 0 ); 
		override def actionPerformed(e: java.awt.event.ActionEvent): Unit = { 
			run()
		} 
	}
	private val loadAction = new AbstractAction() { 
		putValue( Action.NAME, "load \"script\",8,1" ); 
		putValue( Action.DISPLAYED_MNEMONIC_INDEX_KEY, 0 ); 
		override def actionPerformed(e: java.awt.event.ActionEvent): Unit = { 
			load()
		} 
	}
	private val saveAction = new AbstractAction() { 
		putValue( Action.NAME, "save \"script\"" ); 
		putValue( Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_S, java.awt.event.InputEvent.CTRL_MASK) )
		putValue( Action.DISPLAYED_MNEMONIC_INDEX_KEY, 0 ); 
		override def actionPerformed(e: java.awt.event.ActionEvent): Unit = { 
			save()
		} 
	}
	private val saveAsAction = new AbstractAction() { 
		putValue( Action.NAME, "save \"script\" as" ); 
		putValue( Action.DISPLAYED_MNEMONIC_INDEX_KEY, 0 ); 
		override def actionPerformed(e: java.awt.event.ActionEvent): Unit = { 
			saveAs()
		} 
	}

	private val runButton = new javax.swing.JButton(runAction);
	private val loadButton = new javax.swing.JButton(loadAction);
	private val saveButton = new javax.swing.JButton(saveAction);
	
	private val toolBar = new JToolBar(); // Still draggable
	toolBar.add(loadButton)
	toolBar.add(saveButton)
	toolBar.add(runButton)

	add( toolBar, java.awt.BorderLayout.PAGE_START);
	add( splitPane, java.awt.BorderLayout.CENTER );
	splitPane.add( scrollPaneWithEditor );
	splitPane.add( scrollPaneWithOutput );

	//
	// add text changed property
	// with some button-magic-logic
	// 
	private var _textChanged = false
	private def textChanged: Boolean = _textChanged
	private def textChanged_=(b: Boolean): Unit = {
		_textChanged = b;
		saveAction.setEnabled(textChanged)
	}
	textChanged = false;
	editor.getDocument().addDocumentListener(new DocumentListener() {
		override def insertUpdate(e: DocumentEvent): Unit = {
			if (!textChanged) textChanged = true;
		}
		override def removeUpdate(e: DocumentEvent): Unit = {
			if (!textChanged) textChanged = true;
		}
		override def changedUpdate(e: DocumentEvent): Unit = {
			if (!textChanged) textChanged = true;
		}
	})

	def run(): Unit =  {
		try {
			ScalaTool.interpretCode(editor.getText(), Array[String]("x") )
		}
		catch {
		case e:Exception => 
			output.setCaretPosition(output.getText().length())
			output.replaceSelection(e.toString())
		case _ => 
			output.setCaretPosition(output.getText().length())
			output.replaceSelection("unknown error.\n")
		}
	}

	/** @return true if no data was changed, else if data was saved or the used select 'discard changes'. */
	private def alertAndSaveIfSomethingChanged(): Boolean = {
		if (textChanged==true) {
			val possibleValues = Array[Object]( "discard changes", "save script");
			val selectedValue = JOptionPane.showInputDialog(self,
					"There are modifications in the script", "Alert",
					JOptionPane.INFORMATION_MESSAGE, null,
					possibleValues, possibleValues(1));
			//println("selected:"+selectedValue)
			if (selectedValue == possibleValues(0)) {
				true
			}
			else if (selectedValue == possibleValues(1)) {
				save()
				textChanged
			}
			else {
				false
			}
		}
		else {
			true
		}
	}
	
	def load(): Unit = {
		if ( alertAndSaveIfSomethingChanged() ) {
			val file = org.pi.common.dir.FileSelector.selectFile(self,"load")
			if (file!=null) {
				filename = file.getAbsolutePath()
				val text = org.pi.common.text.TextTool.loadTextFromFile( filename )
				editor.setText(text)
				textChanged = false
			}
		}
	}
	
	def saveAs(): Unit = {
		val file = org.pi.common.dir.FileSelector.selectFile(self,"saveAs");
		if (file!=null) {
			filename = file.getCanonicalPath()
			save()
		}
	}
	
	def save(): Unit = {
		if (filename==null) {
			val file = org.pi.common.dir.FileSelector.selectFile(self,"saveAs");
			if (file!=null) filename = file.getCanonicalPath()
		}
		if (filename!=null) {
			val text = editor.getText()
			org.pi.common.text.TextTool.saveTextToFile(filename,text)
			textChanged = false
		}
	}
	
	def connectToFrame(frame: JFrame) {
		val menubar = new JMenuBar();
		val fileMenu = new JMenu("File")
		val scalaMenu = new JMenu("Scala")
		val loadMenu = new JMenuItem(loadAction)
		val saveMenu = new JMenuItem(saveAction)
		val saveAsMenu = new JMenuItem(saveAsAction)
		val runMenu = new JMenuItem(runAction)
		menubar.add(fileMenu)
		fileMenu.add(loadMenu)
		fileMenu.add(saveMenu)
		fileMenu.add(saveAsMenu)
		menubar.add(scalaMenu)
		scalaMenu.add(runMenu)
		
		frame.setJMenuBar(menubar)
		
		frame.addWindowListener(new java.awt.event.WindowAdapter() {
			override def windowClosing(e: java.awt.event.WindowEvent) {
				if ( alertAndSaveIfSomethingChanged() ) {
					//ScalaTool.closeInterpreter()
					frame.dispose()
				}
			}
		})
	}
}

object PragmaticSipRunner {
	def main(args:Array[String]) : Unit = {
		val f = new javax.swing.JFrame();
		f.setLayout( new java.awt.BorderLayout() )
		val runner = new PragmaticSipRunner()
		runner.connectToFrame(f)
	    f.add(java.awt.BorderLayout.CENTER, runner )
	    f.pack()
	    f.setSize(400,550)
	    f.setVisible(true)	
	}
}